home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- #include <sys/types.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <X11/Intrinsic.h>
- #include <X11/Xirisw/GlxMDraw.h>
- #include <Xm/Xm.h>
- #include <gl/gl.h>
-
- #include "shapes.h"
- #include "interfere.h"
-
- #define STEN_SIZE 4
- #define STEN_MASK ((1 << STEN_SIZE) - 1)
-
- /*
- * Material indeces.
- */
- #define BLUE_PLASTIC_INDEX 1
- #define GREEN_PLASTIC_INDEX 2
- #define BRASS_INDEX 3
-
- /*
- * Sundry graphics stuff ... dimensions etc.
- */
- #define VIEWPOINT_Z 8.
- #define PLANE_LENGTH 2.
- #define MAX_CLIP_PLANE 6
- #define ANGLE_DELTA 10
-
- #define NUMBER(array) ((unsigned long) (sizeof(array) / sizeof(array[0])))
-
- typedef struct tagTransformation
- {
- float depth;
- float scale;
- unsigned int x_rot, y_rot, z_rot;
- } Transformation, * TransformationPtr;
-
- /*
- * The viewing, clipping, and modeling transformations are stored
- * in the same array.
- */
- enum
- {
- VIEWING_TRANSFORMATION = 0,
- CLIPPING_TRANSFORMATION,
- MODEL_TRANSFORMATION = CLIPPING_TRANSFORMATION + MAX_CLIP_PLANE
- };
-
- typedef void (*Method) (void);
-
- typedef struct tagShape
- {
- Method constructor;
- GL_Object object;
- unsigned long material;
- Transformation transform;
- } Shape, * ShapePtr;
-
- /*
- * Here are the generalized transforms. The array looks like this :
- * 0 : Viewing transformation.
- * 1-n : Clipping plane transformations.
- * n : Modeling transformation. These are applied to all
- * of the shapes. Transforms applied to one shape only
- * are stored with the shape info.
- */
- static Transformation
- transformations[] = {{VIEWPOINT_Z, 1., 20, 340, 0},
- {0., 1., 0, 180, 0},
- {0., 1., 0, 0, 0},
- {0., 1., 0, 0, 0},
- {0., 1., 0, 0, 0},
- {0., 1., 0, 0, 0},
- {0., 1., 0, 0, 0},
- {0., 1., 0, 0, 0}
- };
-
- /*
- * Shape info.
- */
- static Shape shapes[] = {{ftorus, 0, BLUE_PLASTIC_INDEX, {0., 1., 0, 0, 0}},
- {ftorus, 0, GREEN_PLASTIC_INDEX, {0., 1., 90, 0, 0}},
- };
-
- static Matrix
- identity = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
-
- static GL_Object white_axes = 0;
-
- /*
- * Set up a short far clipping plane.
- */
- static void
- setShortViewingVolume (void)
- {
- perspective(600, 1., 0.25, 15.);
- }
-
- /*
- * Set up a long far clipping plane.
- */
- static void
- setLongViewingVolume (void)
- {
- perspective(600, 1., 0.25, 10000.);
- }
-
- /*
- *
- */
- static void
- setupProjection (void)
- {
- loadmatrix(identity);
- setLongViewingVolume ();
- }
-
- /*
- * Define and bind the lighting model and lights. Define
- * the material indices.
- */
- static void
- defineLighting (void)
- {
- float light_model[] =
- {
- AMBIENT, 0.1, 0.1, 0.1,
- LOCALVIEWER, 0.0,
- TWOSIDE, 1.0,
- LMNULL,
- };
-
- float white_light1[] =
- {
- LCOLOR, 1.0, 1.0, 1.0,
- POSITION, -1., 1, VIEWPOINT_Z, 0.0,
- LMNULL,
- };
-
- float white_light2[] =
- {
- LCOLOR, 1.0, 1.0, 1.0,
- POSITION, 1., 1., VIEWPOINT_Z, 0.0,
- LMNULL,
- };
- float blue_plastic[] =
- {
- AMBIENT, 0.1, 0.1, 0.5,
- DIFFUSE, 0.1, 0.1, 0.5,
- SPECULAR, 0.45, 0.45, 0.45,
- SHININESS, 30.0,
- LMNULL,
- };
-
- float green_plastic[] =
- {
- AMBIENT, 0.1, 0.5, 0.1,
- DIFFUSE, 0.1, 0.5, 0.1,
- SPECULAR, 0.45, 0.45, 0.45,
- SHININESS, 30.0,
- LMNULL,
- };
-
- float brass[] =
- {
- AMBIENT, 0.65, 0.5, 0.35,
- DIFFUSE, 0.65, 0.5, 0.35,
- SPECULAR, 0.0, 0.0, 0.0,
- SHININESS, 5.0,
- LMNULL,
- };
-
- lmdef(DEFMATERIAL, BLUE_PLASTIC_INDEX, 0, blue_plastic);
- lmdef(DEFMATERIAL, GREEN_PLASTIC_INDEX, 0, green_plastic);
- lmdef(DEFMATERIAL, BRASS_INDEX, 0, brass);
- lmdef(DEFLMODEL, 1, 0, light_model);
- lmdef(DEFLIGHT, 1, 0, white_light1);
- lmdef(DEFLIGHT, 2, 0, white_light2);
-
- lmbind(LMODEL, 1);
- lmbind(LIGHT0, 1);
- lmbind(LIGHT1, 2);
- }
-
- /*
- * Create a display list for the axes.
- */
- static void
- whiteAxes(void)
- {
- makeobj(white_axes = genobj());
- cpack(0xffffffff);
- pushmatrix();
- scale(2., 2., 2.);
- axes();
- popmatrix();
- closeobj();
- }
-
- /*
- * Initialize the shapes array.
- */
- static void
- initShapes (void)
- {
- unsigned long i = 0;
-
- for (i = 0; i < NUMBER(shapes); i++) {
- makeobj(shapes[i].object = genobj());
- lmbind(MATERIAL, shapes[i].material);
- (*(shapes[i].constructor))();
- lmbind(MATERIAL, 0);
- closeobj();
- }
- }
-
- /*
- * Entry point to initialize graphics.
- */
- void
- initGraphics (void)
- {
- mmode(MVIEWING);
- zbuffer(TRUE);
- if (!getgdesc(GD_BITS_STENCIL)) {
- fprintf(stderr, "Stenciling is not available\n");
- exit(1);
- }
- sclear(0);
- lsetdepth(getgdesc(GD_ZMIN), getgdesc(GD_ZMAX));
- setupProjection();
- defineLighting ();
- whiteAxes();
- initShapes();
- }
-
- /*
- * Called by the GLwDrawingArea widget before it is managed.
- */
- static void
- initCallback (Widget w, XtPointer client, XtPointer callback)
- {
- GlxDrawCallbackStruct * call_data = (GlxDrawCallbackStruct *)callback;
- GLXwinset(XtDisplay(w), call_data->window);
- initGraphics();
- }
-
- /*
- * Isolated for reshapeviewport()
- */
- static void
- resizeCallback (Widget w, XtPointer client, XtPointer callback)
- {
- reshapeviewport();
- setupProjection();
- }
-
- /*
- * Specify the rendering area, and draw the scene.
- */
- static void
- exposeCallback (Widget w, XtPointer client, XtPointer callback)
- {
- GlxDrawCallbackStruct * call_data = (GlxDrawCallbackStruct *)callback;
- GLXwinset(XtDisplay(w), call_data->window);
- drawScene();
- }
-
- /*
- * Create the GL drawing area widget.
- */
- Widget
- initGLWidget (Widget parent, unsigned int width, unsigned int height)
- {
- GLXconfig rgb_mode[] =
- {
- {GLX_NORMAL, GLX_RGB, TRUE},
- {GLX_NORMAL, GLX_DOUBLE, TRUE},
- {GLX_NORMAL, GLX_ZSIZE, GLX_NOCONFIG},
- {GLX_NORMAL, GLX_STENSIZE, STEN_SIZE},
- {0, 0, 0},
- };
- Arg args[0x20];
- int n = 0;
- Widget canvas;
-
- XtSetArg(args[n], GlxNglxConfig, rgb_mode); n++;
- XtSetArg(args[n], XmNwidth, width); n++;
- XtSetArg(args[n], XmNheight, height); n++;
-
- canvas = (Widget)GlxCreateMDraw(parent, "canvas", args, n);
-
- XtAddCallback(canvas, GlxNginitCallback, initCallback, NULL);
- XtAddCallback(canvas, GlxNexposeCallback, exposeCallback, NULL);
- XtAddCallback(canvas, GlxNresizeCallback, resizeCallback, NULL);
-
- XtManageChild(canvas);
-
- return canvas;
- }
-
- /*
- * Increment the modeling transformation angles (called once for
- * each drawScene()).
- */
- static void
- updateAngles (void)
- {
- transformations[MODEL_TRANSFORMATION].x_rot =
- (transformations[MODEL_TRANSFORMATION].x_rot + ANGLE_DELTA) % 3600;
- transformations[MODEL_TRANSFORMATION].z_rot =
- (transformations[MODEL_TRANSFORMATION].z_rot + ANGLE_DELTA) % 3600;
- }
-
- /*
- * Do the viewing transformation.
- */
- static void
- doViewingTransformation (void)
- {
- translate(0., 0.,-transformations[VIEWING_TRANSFORMATION].depth);
- rot(transformations[VIEWING_TRANSFORMATION].x_rot, 'x');
- rot(transformations[VIEWING_TRANSFORMATION].y_rot, 'y');
- rot(transformations[VIEWING_TRANSFORMATION].z_rot, 'z');
- }
-
- /*
- * Do a modeling (or clipping) and viewing transformation.
- */
- static void
- doTransformation (unsigned int index)
- {
- doViewingTransformation();
- /* Modeling. */
- scale(transformations[index].scale, transformations[index].scale,
- transformations[index].scale);
- translate(0., 0., transformations[index].depth);
- rot(transformations[index].x_rot, 'x');
- rot(transformations[index].y_rot, 'y');
- rot(transformations[index].z_rot, 'z');
- }
-
- /*
- * Do a clipping and viewing transformation.
- */
- static void
- doClippingTransformation (unsigned int clip_plane)
- {
- doTransformation(CLIPPING_TRANSFORMATION + clip_plane);
- }
-
- /*
- * Do a modeling transformation.
- */
- static void
- doModelingTransformation (void)
- {
- doTransformation(MODEL_TRANSFORMATION);
- }
-
- /*
- * Draw the clipping plane. Presumes that the clipping plane is
- * properly oriented.
- */
- static void
- drawClipPlanes (void)
- {
- float clipplane_vertices[4][3] = {
- {PLANE_LENGTH, -PLANE_LENGTH, 0.},
- {-PLANE_LENGTH, -PLANE_LENGTH, 0.},
- {-PLANE_LENGTH, PLANE_LENGTH, 0.},
- {PLANE_LENGTH, PLANE_LENGTH, 0.},
- };
-
- cpack(0xff00ffff);
- bgnclosedline();
- v3f(clipplane_vertices[0]);
- v3f(clipplane_vertices[1]);
- v3f(clipplane_vertices[2]);
- v3f(clipplane_vertices[3]);
- endclosedline();
- cpack(0x0000000000);
- }
-
- /*
- * Draw a capping rectangle over clipped portions of
- * a shape.
- *
- */
- static void
- drawCap (unsigned long cap_color)
- {
- float cap_vertices[4][4] = {
- {-1, -1, 0., 1.},
- { 1, -1, 0., 1.},
- {-1, 1, 0., 1.},
- { 1, 1, 0., 1.},
- };
-
- /*
- Always update the z values. Turn on stenciling and increment
- for each pixel that has a count equal to one. This means
- that we will only draw where we did not draw before. Doing
- the clipping transform after this is crucial.
- */
- zfunction(ZF_ALWAYS);
- stencil(TRUE, 1, SF_EQUAL, 0x1, ST_KEEP, ST_KEEP, ST_INCR);
- clipplane(0, CP_OFF, 0);
-
- pushmatrix();
- /*
- Go to the location of the clipping plane.
- */
- doClippingTransformation(0);
-
- /*
- * Cap in the same material as the shape.
- */
- lmbind(MATERIAL, cap_color);
- pushmatrix();
-
- /*
- * Make the polygon enormous enough to cover the exposed portion
- * of the clipped polygon.
- */
- scale(100., 100., 100.);
- bgnpolygon();
- v3f(cap_vertices[0]);
- v3f(cap_vertices[2]);
- v3f(cap_vertices[3]);
- v3f(cap_vertices[1]);
- endpolygon();
- popmatrix();
- lmbind(MATERIAL, 0);
- popmatrix();
-
- /*
- * Restore the zbuffer and stencil buffer states.
- */
- zfunction(ZF_LEQUAL);
- stencil(FALSE, 0, 0, 0, 0, 0, 0);
- }
-
- /*
- * Render a shape (clipped, not yet capped). The shape's
- * transformations must be applied relative to the overall
- * modeling transformation. It appears that storing a
- * transformation in a display list simply does a loadmatrix()
- * and no multiply relative to the MVM when the display list
- * is called.
- */
- static void
- drawObject (unsigned long index)
- {
- pushmatrix();
- scale(shapes[index].transform.scale, shapes[index].transform.scale,
- shapes[index].transform.scale);
- translate(0., 0., shapes[index].transform.depth);
- rot(shapes[index].transform.x_rot, 'x');
- rot(shapes[index].transform.y_rot, 'y');
- rot(shapes[index].transform.z_rot, 'z');
- callobj(shapes[index].object);
- popmatrix();
- }
-
- /*
- * Draw a capped shape.
- */
- static void
- drawCappedObject (unsigned long index)
- {
- pushmatrix();
-
- /*
- * This is the overall modeling transformation.
- */
- doModelingTransformation();
-
- /*
- * Turn the clipping plane on and enable backface culling
- * (since we don't need to draw what we won't see due to the
- * capping anyway). Then draw the uncapped object.
- */
- clipplane(0, CP_ON, 0);
- backface(TRUE);
- drawObject(index);
- backface(FALSE);
-
- /*
- * Set up a short far clipping plane in the viewing volume.
- * Render the shape again, this time writing only to the
- * stencil buffer. This time we're gathering the information
- * that will tell us which parts of the shape need to be capped
- * (referenced by pixel).
- */
- setShortViewingVolume();
- zbuffer(FALSE);
- wmpack(0x00000000);
- swritemask(0x1);
-
- /*
- * Check the LSB of the stencil value for a hit by the rendered
- * object. Count even-odd.
- */
- stencil(TRUE, 0, SF_ALWAYS, 0x01, ST_INVERT, ST_INVERT, ST_INVERT);
- drawObject(index);
- setLongViewingVolume();
- zbuffer(TRUE);
- wmpack(0xffffffff);
- swritemask(0xff);
- popmatrix();
-
- /*
- * Draw the capped regions.
- */
- drawCap (shapes[index].material);
- }
-
- /*
- * Render the intersections in red.
- */
- static void
- drawInterferenceRegion (void)
- {
- stencil(TRUE, 2, SF_LESS, STEN_MASK, ST_ZERO, ST_ZERO, ST_ZERO);
- zfunction(ZF_ALWAYS);
-
- /*
- * Set the projection matrix to a 2d orthographic projection
- * and render a polygon over the entire porjection area. It will
- * only show up in the areas in which the stencil values are
- * two or more.
- */
- ortho2(0, 1, 0, 1);
- pushmatrix();
- loadmatrix(identity);
- cpack(0x0000ff);
- rectfi(0, 0, 1, 1);
- popmatrix();
- setLongViewingVolume ();
-
- zfunction(ZF_LEQUAL);
- stencil(FALSE, 0, 0, 0, 0, 0, 0);
- }
-
- /*
- * Draw the interfering objects, swap the buffers, and update the
- * angles for rotation.
- */
- void
- drawScene (void)
- {
- unsigned long i = 0;
- float cp[4] = {0, 0, 1, 0};
-
- swritemask(0xff);
- czclear(0x0, getgdesc(GD_ZMAX));
-
- /* Define the clipping plane after setting up the
- proper model view matrix. */
- pushmatrix();
- doClippingTransformation(0);
- clipplane(0, CP_DEFINE, cp);
- popmatrix();
-
- pushmatrix();
- doViewingTransformation();
- callobj(white_axes);
- drawClipPlanes ();
- popmatrix();
-
- pushmatrix();
- for (i = 0; i < NUMBER(shapes); i++) {
- drawCappedObject(i);
- }
- drawInterferenceRegion();
- popmatrix();
-
- swapbuffers();
-
- updateAngles();
- }
-
-